gtk_render_activity
gtk_render_icon_pixbuf
gtk_render_icon
+gtk_render_insertion_cursor
<SUBSECTION Standard>
GTK_TYPE_STYLE_CONTEXT
gtk_render_handle
gtk_render_icon
gtk_render_icon_pixbuf
+gtk_render_insertion_cursor
gtk_render_layout
gtk_render_line
gtk_render_option
{
GtkEntryPrivate *priv = entry->priv;
GtkWidget *widget = GTK_WIDGET (entry);
- GdkKeymap *keymap = gdk_keymap_get_for_display (gtk_widget_get_display (widget));
- PangoDirection keymap_direction = gdk_keymap_get_direction (keymap);
- GdkRectangle cursor_location;
- gboolean split_cursor;
+ GtkStyleContext *context;
PangoRectangle cursor_rect;
- GtkBorder inner_border;
- gint xoffset;
- gint text_area_height;
gint cursor_index;
gboolean block;
gboolean block_at_line_end;
PangoLayout *layout;
const char *text;
- _gtk_entry_effective_inner_border (entry, &inner_border);
-
- xoffset = inner_border.left - priv->scroll_offset;
-
- text_area_height = gdk_window_get_height (priv->text_area);
+ context = gtk_widget_get_style_context (widget);
layout = gtk_entry_ensure_layout (entry, TRUE);
text = pango_layout_get_text (layout);
cursor_index = g_utf8_offset_to_pointer (text, priv->current_pos + priv->preedit_cursor) - text;
+
if (!priv->overwrite_mode)
block = FALSE;
else
if (!block)
{
- gint strong_x, weak_x;
- GtkTextDirection dir1, dir2;
- gint x1 = 0;
- gint x2 = 0;
-
- gtk_entry_get_cursor_locations (entry, type, &strong_x, &weak_x);
-
- g_object_get (gtk_widget_get_settings (widget),
- "gtk-split-cursor", &split_cursor,
- NULL);
-
- dir1 = (priv->resolved_dir == PANGO_DIRECTION_LTR) ? GTK_TEXT_DIR_LTR : GTK_TEXT_DIR_RTL;
- dir2 = GTK_TEXT_DIR_NONE;
-
- if (split_cursor)
- {
- x1 = strong_x;
-
- if (weak_x != strong_x)
- {
- dir2 = (priv->resolved_dir == PANGO_DIRECTION_LTR) ? GTK_TEXT_DIR_RTL : GTK_TEXT_DIR_LTR;
- x2 = weak_x;
- }
- }
- else
- {
- if (keymap_direction == priv->resolved_dir)
- x1 = strong_x;
- else
- x1 = weak_x;
- }
-
- cursor_location.x = xoffset + x1;
- cursor_location.y = inner_border.top;
- cursor_location.width = 0;
- cursor_location.height = text_area_height - inner_border.top - inner_border.bottom;
+ GtkBorder inner_border;
- gtk_draw_insertion_cursor (widget, cr,
- &cursor_location, TRUE, dir1,
- dir2 != GTK_TEXT_DIR_NONE);
+ _gtk_entry_effective_inner_border (entry, &inner_border);
- if (dir2 != GTK_TEXT_DIR_NONE)
- {
- cursor_location.x = xoffset + x2;
- gtk_draw_insertion_cursor (widget, cr,
- &cursor_location, FALSE, dir2,
- TRUE);
- }
+ gtk_render_insertion_cursor (context, cr,
+ inner_border.left - priv->scroll_offset, inner_border.top,
+ layout, cursor_index, priv->resolved_dir);
}
else /* overwrite_mode */
{
- GtkStyleContext *context;
GdkRGBA cursor_color;
GdkRectangle rect;
gint x, y;
rect.width = PANGO_PIXELS (cursor_rect.width);
rect.height = PANGO_PIXELS (cursor_rect.height);
- context = gtk_widget_get_style_context (widget);
-
_gtk_style_context_get_cursor_color (context, &cursor_color, NULL);
gdk_cairo_set_source_rgba (cr, &cursor_color);
gdk_cairo_rectangle (cr, &rect);
return PANGO_DIRECTION_LTR;
}
-static void
-gtk_label_draw_cursor (GtkLabel *label, cairo_t *cr, gint xoffset, gint yoffset)
-{
- GtkLabelPrivate *priv = label->priv;
- GtkWidget *widget;
-
- if (priv->select_info == NULL)
- return;
-
- widget = GTK_WIDGET (label);
-
- if (gtk_widget_is_drawable (widget))
- {
- PangoDirection keymap_direction;
- PangoDirection cursor_direction;
- PangoRectangle strong_pos, weak_pos;
- GtkTextDirection dir1, dir2;
- gboolean split_cursor;
- PangoRectangle *cursor1 = NULL;
- PangoRectangle *cursor2 = NULL;
- GdkRectangle cursor_location;
-
- keymap_direction = gdk_keymap_get_direction (gdk_keymap_get_for_display (gtk_widget_get_display (widget)));
- cursor_direction = get_cursor_direction (label);
-
- gtk_label_ensure_layout (label);
-
- pango_layout_get_cursor_pos (priv->layout, priv->select_info->selection_end,
- &strong_pos, &weak_pos);
-
- g_object_get (gtk_widget_get_settings (widget),
- "gtk-split-cursor", &split_cursor,
- NULL);
-
- dir1 = (cursor_direction == PANGO_DIRECTION_LTR) ? GTK_TEXT_DIR_LTR : GTK_TEXT_DIR_RTL;
- dir2 = GTK_TEXT_DIR_NONE;
-
- if (split_cursor)
- {
- cursor1 = &strong_pos;
-
- if (strong_pos.x != weak_pos.x || strong_pos.y != weak_pos.y)
- {
- dir2 = (cursor_direction == PANGO_DIRECTION_LTR) ? GTK_TEXT_DIR_RTL : GTK_TEXT_DIR_LTR;
- cursor2 = &weak_pos;
- }
- }
- else
- {
- if (keymap_direction == cursor_direction)
- cursor1 = &strong_pos;
- else
- cursor1 = &weak_pos;
- }
-
- cursor_location.x = xoffset + PANGO_PIXELS (cursor1->x);
- cursor_location.y = yoffset + PANGO_PIXELS (cursor1->y);
- cursor_location.width = 0;
- cursor_location.height = PANGO_PIXELS (cursor1->height);
-
- gtk_draw_insertion_cursor (widget, cr,
- &cursor_location, TRUE, dir1,
- dir2 != GTK_TEXT_DIR_NONE);
-
- if (dir2 != GTK_TEXT_DIR_NONE)
- {
- cursor_location.x = xoffset + PANGO_PIXELS (cursor2->x);
- cursor_location.y = yoffset + PANGO_PIXELS (cursor2->y);
- cursor_location.width = 0;
- cursor_location.height = PANGO_PIXELS (cursor2->height);
-
- gtk_draw_insertion_cursor (widget, cr,
- &cursor_location, FALSE, dir2,
- TRUE);
- }
- }
-}
-
static GtkLabelLink *
gtk_label_get_focus_link (GtkLabel *label)
{
GdkColor *link_color;
GdkColor *visited_link_color;
- if (info->selectable && gtk_widget_has_focus (widget))
- gtk_label_draw_cursor (label, cr, x, y);
+ if (info->selectable &&
+ gtk_widget_has_focus (widget) &&
+ gtk_widget_is_drawable (widget))
+ {
+ PangoDirection cursor_direction;
+
+ cursor_direction = get_cursor_direction (label);
+ gtk_render_insertion_cursor (context, cr,
+ x, y,
+ priv->layout, priv->select_info->selection_end,
+ cursor_direction);
+ }
focus_link = gtk_label_get_focus_link (label);
active_link = info->active_link;
cairo_restore (cr);
}
-/**
- * gtk_draw_insertion_cursor:
- * @widget: a #GtkWidget
- * @cr: cairo context to draw to
- * @location: location where to draw the cursor (@location->width is ignored)
- * @is_primary: if the cursor should be the primary cursor color.
- * @direction: whether the cursor is left-to-right or
- * right-to-left. Should never be #GTK_TEXT_DIR_NONE
- * @draw_arrow: %TRUE to draw a directional arrow on the
- * cursor. Should be %FALSE unless the cursor is split.
- *
- * Draws a text caret on @cr at @location. This is not a style function
- * but merely a convenience function for drawing the standard cursor shape.
- *
- * Since: 3.0
- */
-void
-gtk_draw_insertion_cursor (GtkWidget *widget,
- cairo_t *cr,
- const GdkRectangle *location,
- gboolean is_primary,
- GtkTextDirection direction,
- gboolean draw_arrow)
+static void
+draw_insertion_cursor (GtkStyleContext *context,
+ cairo_t *cr,
+ gdouble x,
+ gdouble y,
+ gdouble height,
+ gboolean is_primary,
+ PangoDirection direction,
+ gboolean draw_arrow)
+
{
- gint stem_width;
- gint arrow_width;
- gint x, y;
- gfloat cursor_aspect_ratio;
- gint offset;
- GtkStyleContext *context;
GdkRGBA primary_color;
GdkRGBA secondary_color;
+ gfloat cursor_aspect_ratio;
+ gint stem_width;
+ gint offset;
- g_return_if_fail (GTK_IS_WIDGET (widget));
- g_return_if_fail (cr != NULL);
- g_return_if_fail (location != NULL);
- g_return_if_fail (direction != GTK_TEXT_DIR_NONE);
-
- context = gtk_widget_get_style_context (widget);
+ cairo_save (cr);
_gtk_style_context_get_cursor_color (context, &primary_color, &secondary_color);
gdk_cairo_set_source_rgba (cr, is_primary ? &primary_color : &secondary_color);
"cursor-aspect-ratio", &cursor_aspect_ratio,
NULL);
- stem_width = location->height * cursor_aspect_ratio + 1;
- arrow_width = stem_width + 1;
+ stem_width = height * cursor_aspect_ratio + 1;
/* put (stem_width % 2) on the proper side of the cursor */
- if (direction == GTK_TEXT_DIR_LTR)
+ if (direction == PANGO_DIRECTION_LTR)
offset = stem_width / 2;
else
offset = stem_width - stem_width / 2;
- cairo_rectangle (cr,
- location->x - offset, location->y,
- stem_width, location->height);
+ cairo_rectangle (cr, x - offset, y, stem_width, height);
cairo_fill (cr);
if (draw_arrow)
{
- if (direction == GTK_TEXT_DIR_RTL)
+ gint arrow_width;
+ gint ax, ay;
+
+ arrow_width = stem_width + 1;
+
+ if (direction == PANGO_DIRECTION_RTL)
{
- x = location->x - offset - 1;
- y = location->y + location->height - arrow_width * 2 - arrow_width + 1;
+ ax = x - offset - 1;
+ ay = y + height - arrow_width * 2 - arrow_width + 1;
- cairo_move_to (cr, x, y + 1);
- cairo_line_to (cr, x - arrow_width, y + arrow_width);
- cairo_line_to (cr, x, y + 2 * arrow_width);
+ cairo_move_to (cr, ax, ay + 1);
+ cairo_line_to (cr, ax - arrow_width, ay + arrow_width);
+ cairo_line_to (cr, ax, ay + 2 * arrow_width);
cairo_fill (cr);
}
- else if (direction == GTK_TEXT_DIR_LTR)
+ else if (direction == PANGO_DIRECTION_LTR)
{
- x = location->x + stem_width - offset;
- y = location->y + location->height - arrow_width * 2 - arrow_width + 1;
+ ax = x + stem_width - offset;
+ ay = y + height - arrow_width * 2 - arrow_width + 1;
- cairo_move_to (cr, x, y + 1);
- cairo_line_to (cr, x + arrow_width, y + arrow_width);
- cairo_line_to (cr, x, y + 2 * arrow_width);
+ cairo_move_to (cr, ax, ay + 1);
+ cairo_line_to (cr, ax + arrow_width, ay + arrow_width);
+ cairo_line_to (cr, ax, ay + 2 * arrow_width);
cairo_fill (cr);
}
+ else
+ g_assert_not_reached();
}
+
+ cairo_restore (cr);
+}
+
+/**
+ * gtk_render_insertion_cursor:
+ * @context: a #GtkStyleContext
+ * @cr: a #cairo_t
+ * @x: X origin
+ * @y: Y origin
+ * @layout: the #PangoLayout of the text
+ * @index: the index in the #PangoLayout
+ * @direction: the #PangoDirection of the text
+ *
+ * Draws a text caret on @cr at the specified index of @layout.
+ *
+ * Since: 3.4
+ **/
+void
+gtk_render_insertion_cursor (GtkStyleContext *context,
+ cairo_t *cr,
+ gdouble x,
+ gdouble y,
+ PangoLayout *layout,
+ int index,
+ PangoDirection direction)
+{
+ GtkStyleContextPrivate *priv;
+ gboolean split_cursor;
+ PangoRectangle strong_pos, weak_pos;
+ PangoRectangle *cursor1, *cursor2;
+ PangoDirection keymap_direction;
+ PangoDirection direction2;
+
+ g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
+ g_return_if_fail (cr != NULL);
+ g_return_if_fail (PANGO_IS_LAYOUT (layout));
+ g_return_if_fail (index >= 0);
+
+ priv = context->priv;
+
+ g_object_get (gtk_settings_get_for_screen (priv->screen),
+ "gtk-split-cursor", &split_cursor,
+ NULL);
+
+ keymap_direction = gdk_keymap_get_direction (gdk_keymap_get_for_display (gdk_screen_get_display (priv->screen)));
+
+ pango_layout_get_cursor_pos (layout, index, &strong_pos, &weak_pos);
+
+ direction2 = PANGO_DIRECTION_NEUTRAL;
+
+ if (split_cursor)
+ {
+ cursor1 = &strong_pos;
+
+ if (strong_pos.x != weak_pos.x || strong_pos.y != weak_pos.y)
+ {
+ direction2 = (direction == PANGO_DIRECTION_LTR) ? PANGO_DIRECTION_RTL : PANGO_DIRECTION_LTR;
+ cursor2 = &weak_pos;
+ }
+ }
+ else
+ {
+ if (keymap_direction == direction)
+ cursor1 = &strong_pos;
+ else
+ cursor1 = &weak_pos;
+ }
+
+ draw_insertion_cursor (context,
+ cr,
+ x + PANGO_PIXELS (cursor1->x),
+ y + PANGO_PIXELS (cursor1->y),
+ PANGO_PIXELS (cursor1->height),
+ TRUE,
+ direction,
+ direction2 != PANGO_DIRECTION_NEUTRAL);
+
+ if (direction2 != PANGO_DIRECTION_NEUTRAL)
+ {
+ draw_insertion_cursor (context,
+ cr,
+ x + PANGO_PIXELS (cursor2->x),
+ y + PANGO_PIXELS (cursor2->y),
+ PANGO_PIXELS (cursor2->height),
+ FALSE,
+ direction2,
+ TRUE);
+ }
+}
+
+/**
+ * gtk_draw_insertion_cursor:
+ * @widget: a #GtkWidget
+ * @cr: cairo context to draw to
+ * @location: location where to draw the cursor (@location->width is ignored)
+ * @is_primary: if the cursor should be the primary cursor color.
+ * @direction: whether the cursor is left-to-right or
+ * right-to-left. Should never be #GTK_TEXT_DIR_NONE
+ * @draw_arrow: %TRUE to draw a directional arrow on the
+ * cursor. Should be %FALSE unless the cursor is split.
+ *
+ * Draws a text caret on @cr at @location. This is not a style function
+ * but merely a convenience function for drawing the standard cursor shape.
+ *
+ * Since: 3.0
+ */
+void
+gtk_draw_insertion_cursor (GtkWidget *widget,
+ cairo_t *cr,
+ const GdkRectangle *location,
+ gboolean is_primary,
+ GtkTextDirection direction,
+ gboolean draw_arrow)
+{
+ GtkStyleContext *context;
+
+ g_return_if_fail (GTK_IS_WIDGET (widget));
+ g_return_if_fail (cr != NULL);
+ g_return_if_fail (location != NULL);
+ g_return_if_fail (direction != GTK_TEXT_DIR_NONE);
+
+ context = gtk_widget_get_style_context (widget);
+
+ draw_insertion_cursor (context, cr,
+ location->x, location->y, location->height,
+ is_primary,
+ (direction == GTK_TEXT_DIR_RTL) ? PANGO_DIRECTION_RTL : PANGO_DIRECTION_LTR,
+ draw_arrow);
}
static AtkAttributeSet *
GdkPixbuf *pixbuf,
gdouble x,
gdouble y);
+void gtk_render_insertion_cursor
+ (GtkStyleContext *context,
+ cairo_t *cr,
+ gdouble x,
+ gdouble y,
+ PangoLayout *layout,
+ int index,
+ PangoDirection direction);
void gtk_draw_insertion_cursor (GtkWidget *widget,
cairo_t *cr,
cairo_t *cr,
GList **widgets)
{
+ GtkStyleContext *context;
gint offset_y;
GtkTextRenderer *text_renderer;
GtkTextIter selection_start, selection_end;
if (!gdk_cairo_get_clip_rectangle (cr, &clip))
return;
+ context = gtk_widget_get_style_context (widget);
+
line_list = gtk_text_layout_get_lines (layout, clip.y, clip.y + clip.height, &offset_y);
if (line_list == NULL)
for (i = 0; i < line_display->cursors->len; i++)
{
int index;
- PangoRectangle strong_pos, weak_pos;
- PangoRectangle *cursor1, *cursor2;
- gboolean split_cursor;
- GtkTextDirection dir1, dir2;
- GdkRectangle cursor_location;
+ PangoDirection dir;
index = g_array_index(line_display->cursors, int, i);
- pango_layout_get_cursor_pos (line_display->layout, index, &strong_pos, &weak_pos);
-
- dir1 = line_display->direction;
- dir2 = GTK_TEXT_DIR_NONE;
-
- g_object_get (gtk_widget_get_settings (widget),
- "gtk-split-cursor", &split_cursor,
- NULL);
-
- if (split_cursor)
- {
- cursor1 = &strong_pos;
- if (strong_pos.x != weak_pos.x || strong_pos.y != weak_pos.y)
- {
- dir2 = (line_display->direction == GTK_TEXT_DIR_LTR) ? GTK_TEXT_DIR_RTL : GTK_TEXT_DIR_LTR;
- cursor2 = &weak_pos;
- }
- }
- else
- {
- if (layout->keyboard_direction == line_display->direction)
- cursor1 = &strong_pos;
- else
- cursor1 = &weak_pos;
- }
-
- cursor_location.x = line_display->x_offset + PANGO_PIXELS (cursor1->x);
- cursor_location.y = line_display->top_margin + PANGO_PIXELS (cursor1->y);
- cursor_location.width = 0;
- cursor_location.height = PANGO_PIXELS (cursor1->height);
-
- gtk_draw_insertion_cursor (widget, cr,
- &cursor_location, TRUE, dir1,
- dir2 != GTK_TEXT_DIR_NONE);
-
- if (dir2 != GTK_TEXT_DIR_NONE)
- {
- cursor_location.x = line_display->x_offset + PANGO_PIXELS (cursor2->x);
- cursor_location.y = line_display->top_margin + PANGO_PIXELS (cursor2->y);
- cursor_location.width = 0;
- cursor_location.height = PANGO_PIXELS (cursor2->height);
-
- gtk_draw_insertion_cursor (widget, cr,
- &cursor_location, FALSE, dir2,
- TRUE);
- }
+ dir = (line_display->direction == GTK_TEXT_DIR_RTL) ? PANGO_DIRECTION_RTL : PANGO_DIRECTION_LTR;
+ gtk_render_insertion_cursor (context, cr,
+ line_display->x_offset, line_display->top_margin,
+ line_display->layout, index, dir);
}
}
} /* line_display->height > 0 */
-
+
cairo_translate (cr, 0, line_display->height);
gtk_text_layout_free_line_display (layout, line_display);
gtk_text_layout_get_cursor_locations (priv->layout, &iter,
&strong, &weak);
- /* cursor width calculation as in gtkstyle.c:draw_insertion_cursor(),
+ /* cursor width calculation as in gtkstylecontext.c:draw_insertion_cursor(),
* ignoring the text direction be exposing both sides of the cursor
*/